<template>
	<view @click="showCity = !props.disabled ? !showCity : false">
		<!-- #ifdef APP-NVUE -->
		<view :eventPenetrationEnabled="true">
			<slot></slot>
		</view>
		<!-- #endif -->
		<!-- #ifndef APP-NVUE -->
		<slot></slot>
		<!-- #endif -->
		<tm-drawer
			:disabbleScroll="true"
			:round="props.round"
			ref="drawer"
			:height="820"
			:closable="true"
			:overlayClick="aniover"
			@open="drawerOpen"
			@cancel="cancel"
			@ok="confirm"
			:show="showCity"
			@update:show="closeDrawer"
			title="请选择地区"
			ok-text="确认"
			:duration="props.duration"
		>
			<tm-picker-view
				v-if="showCity"
				ref="picker"
				:height="590"
				@end="aniover = true"
				@start="aniover = false"
				:value="_colIndex"
				@update:modelValue="_colIndex = $event"
				@update:model-str="_colStr = $event"
				:model-str="_colStr"
				:default-value="_colIndex"
				:columns="_data"
				:ok-color="props.color"
			></tm-picker-view>
			<tm-button
				label="确认选择"
				block
				:margin="[32, 12]"
				:color="props.color"
				:linear="props.linear"
				:linear-deep="props.linearDeep"
				@click="confirm"
				:round="props.btnRound"
			></tm-button>
			<view :style="{ height: win_bottom + 'px' }"></view>
		</tm-drawer>
	</view>
</template>
<script lang="ts" setup>
/**
 * 地区选择器
 * @description 这是弹出式，滑动地址选择器，另还一个按步选择地区的组件，见：tm-city-cascader
 * @example <tm-city-picker v-model:show="show" v-model="status" v-model:model-str="statusw"></tm-city-picker>
 */
import { PropType, inject, Ref, ref, watchEffect, getCurrentInstance, watch, toRaw, computed, nextTick, onMounted } from 'vue'
import { custom_props } from '../../tool/lib/minxs'
import tmDrawer from '../tm-drawer/tm-drawer.vue'
import { childrenData } from './interface'
import { provinceData } from '../../tool/static/province'
import { cityData } from '../../tool/static/city'
import { areaData } from '../../tool/static/area'
import tmPickerView from '../tm-picker-view/tm-picker-view.vue'
import TmSheet from '../tm-sheet/tm-sheet.vue'
import tmText from '../tm-text/tm-text.vue'
import tmButton from '../tm-button/tm-button.vue'
const proxy = getCurrentInstance()?.proxy ?? null
const drawer = ref<InstanceType<typeof tmDrawer> | null>(null)
const picker = ref<InstanceType<typeof tmPickerView> | null>(null)

/**
 * 事件说明：
 * v-model:show 双向绑定显示和隐藏选择器
 * v-model 双向绑定以selectedModel为模式的值。一般用来给数据库后台用的。
 * v-model:model-str 单向输出地区名称，
 * 一般用来绑定在Input组件或者其它组件上用来展示当前选择的地址名称，
 * 但我们服务器可能有的是id或者index，所以你可以v-model绑定数据，用此v-model:model-str来显示数据。
 * confirm 点击了确认按钮时触发，返回当前选择数据。
 * cancel 取消或者点击遮罩关闭了选择器都将触发。
 */
const emits = defineEmits(['update:show', 'update:modelValue', 'update:modelStr', 'confirm', 'cancel'])
const props = defineProps({
	...custom_props,
	followTheme: {
		type: [Boolean, String],
		default: true
	},
	//v-model以selectedModel为索引的值结果。
	modelValue: {
		type: Array as PropType<Array<string | number>>,
		default: () => []
	},
	//单向输出地区名称以/分割。不管selectedModel是以哪种索引选项，此处始终以地区名称输出显示。
	//可以使用v-model:modelStr，外部不可更改。
	modelStr: {
		type: String,
		default: ''
	},
	//v-model:show来双向绑定显示和隐藏选择器。
	show: {
		type: [Boolean],
		default: false
	},
	//赋值和选值方式
	//name:名称模式赋值和选择
	//id:地区id模式赋值和选择
	//index:索引模式赋值和选择
	selectedModel: {
		type: String,
		default: 'id'
	},
	/**
	 * 城市选择的级别
	 * province:省级别。
	 * city:省，市
	 * area:省，市，县/区.
	 */
	cityLevel: {
		type: String,
		default: 'area'
	},
	// 手动赋值城市数据
	city: {
		type: Array as PropType<Array<childrenData>>,
		default: () => []
	},
	color: {
		type: String,
		default: 'primary'
	},
	linear: {
		type: String,
		default: ''
	},
	linearDeep: {
		type: String,
		default: 'light'
	},
	btnRound: {
		type: Number,
		default: 3
	},
	round: {
		type: Number,
		default: 12
	},
	/**禁用时，通过插槽点击时，不会触发显示本组件，适合表单 */
	disabled: {
		type: Boolean,
		default: false
	},
	//弹出的动画时间单位ms.
	duration: {
		type: Number,
		default: 300
	}
})
const showCity = ref(true)
const _cityData = computed(() => props.city)
const _colIndex: Ref<Array<number>> = ref([])
const _data = ref(chiliFormatCity_area())
let tmid: any = NaN
const _colStr = ref('')
const aniover = ref(true)
const sysinfo = inject('tmuiSysInfo', {
	bottom: 0,
	height: 750,
	width: uni.upx2px(750),
	top: 0,
	isCustomHeader: false,
	sysinfo: null
})
let win_bottom = sysinfo.bottom

watchEffect(() => {
	showCity.value = props.show
})
watch(
	[() => props.city, () => props.modelValue],
	() => {
		_data.value = chiliFormatCity_area()
		clearTimeout(tmid)
		tmid = setTimeout(function () {
			getIndexBymodel(_data.value, props.selectedModel, 0, props.modelValue)
			defaultModerStrGet()
		}, 500)
	},
	{ deep: true }
)
function closeDrawer(e: boolean) {
	showCity.value = e
	emits('update:show', showCity.value)
	getIndexBymodel(_data.value, 'index', 0, toRaw(_colIndex.value))
}
// onMounted(()=>defaultModerStrGet())
function drawerOpen() {
	getIndexBymodel(_data.value, props.selectedModel, 0, props.modelValue)
}
//点击确认了地区。
function confirm() {
	if (!aniover.value) return
	setVal()
	nextTick(() => {
		emits('confirm', props.modelValue)
		drawer.value?.close()
	})
}
function cancel() {
	if (!aniover.value) return
	emits('cancel')
}
function setVal() {
	let val = []
	if (props.selectedModel == 'name') {
		val = _colStr.value.split('/') ?? []
	} else if (props.selectedModel == 'id') {
		val = getRouterId(_data.value, 0)
	} else {
		val = [..._colIndex.value]
	}

	emits('update:modelValue', val)
	emits('update:modelStr', _colStr.value)
}
function defaultModerStrGet() {
	clearTimeout(tmid)
	tmid = setTimeout(function () {
		if (_colIndex.value.length > 0) {
			let text = getRouterText(_data.value, 0)
			emits('update:modelStr', text.join('/'))
		}
	}, 200)
}
//模拟模型来返回index值
function getIndexBymodel(
	vdata: Array<childrenData> = [],
	model = 'name',
	parentIndex = 0,
	value: Array<number | string> = []
): Array<number | string> {
	if (value.length == 0) return []
	if (model == 'name') {
		let item: any = vdata.filter((el) => value[parentIndex] == el['text'])
		if (item.length == 0) {
			item = vdata[0]
			if (item) {
				value[parentIndex] = item['text']
				_colIndex.value[parentIndex] = 0
				if (item['children']) {
					getIndexBymodel(item['children'], model, parentIndex + 1, value)
				}
			}
		} else {
			item = item[0]
			if (item) {
				_colIndex.value[parentIndex] = vdata.findIndex((el) => el['text'] == item['text'])
				if (item['children']) {
					getIndexBymodel(item['children'], model, parentIndex + 1, value)
				}
			}
		}
	} else if (model == 'id') {
		let item: any = vdata.filter((el) => value[parentIndex] == el['id'])
		if (item.length == 0) {
			item = vdata[0]
			if (item) {
				value[parentIndex] = item['id']
				_colIndex.value[parentIndex] = 0
				if (item['children']) {
					getIndexBymodel(item['children'], model, parentIndex + 1, value)
				}
			}
		} else {
			item = item[0]
			if (item) {
				_colIndex.value[parentIndex] = vdata.findIndex((el) => el['id'] == item['id'])
				if (item['children']) {
					getIndexBymodel(item['children'], model, parentIndex + 1, value)
				}
			}
		}
	}

	return _colIndex.value
}
//返回 一个节点从父到子的路径id组。
function getRouterId(list: Array<childrenData> = [], parentIndex = 0, value: Array<number | string> = []): Array<string | number> {
	let p: Array<string | number> = []
	const _defalutValue = value.length == 0 ? _colIndex.value : value
	for (let i = 0; i < list.length; i++) {
		if (i == _defalutValue[parentIndex]) {
			p.push(list[i]['id'])
			if (typeof _defalutValue[parentIndex] != 'undefined') {
				let c = getRouterId(list[i]['children'], parentIndex + 1)
				p = [...p, ...c]
			}
			break
		}
	}
	return p
}
//返回 一个节点从父到子的路径text组。
function getRouterText(list: Array<childrenData> = [], parentIndex = 0): Array<string | number> {
	let p: Array<string | number> = []
	for (let i = 0; i < list.length; i++) {
		if (i == _colIndex.value[parentIndex]) {
			p.push(list[i]['text'])
			if (typeof _colIndex.value[parentIndex] != 'undefined') {
				let c = getRouterText(list[i]['children'], parentIndex + 1)
				p = [...p, ...c]
			}
			break
		}
	}
	return p
}
//格式化数据格式。
function chiliFormatCity_area() {
	let list: Array<childrenData> = []

	if (_cityData.value.length > 0) {
		return _cityData.value
	}

	provinceData.forEach((item: childrenData, index: number) => {
		list.push({
			id: item.value ?? '',
			text: String(item.label),
			children: []
		})
	})
	if (props.cityLevel == 'province') return list
	cityData.forEach((item: childrenData, index: number) => {
		item.forEach((citem: childrenData, cindex: number) => {
			list[index]?.children.push({
				id: citem.value ?? '',
				text: citem.label ?? '',
				children: []
			})
		})
	})
	if (props.cityLevel == 'city') return list
	list.forEach((item, index) => {
		item.children.forEach((citem, cindex: number) => {
			areaData[index][cindex].forEach((jitem) => {
				list[index]?.children[cindex]?.children.push({
					id: jitem.value ?? '',
					text: jitem.label ?? ''
				})
			})
		})
	})

	return list
}

defineExpose({
	getList: chiliFormatCity_area,
	getIndexs: getIndexBymodel,
	getRouterId
})
</script>
